package com.log4jviewer.logfile;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.text.ParseException;
import java.util.regex.Pattern;

import com.log4jviewer.LogEventContainer;
import com.log4jviewer.LogEventListener;
import com.log4jviewer.domain.FileLogEvent;
import com.log4jviewer.domain.LogEvent;

/**
 * Class provides functionality for reading logs from text files using specified log format (pattern).
 * 
 * @author <a href="mailto:rd.ryly@gmail.com">Ruslan Diachenko</a>
 */
public class LogFileLoader {

    private LogEventContainer logEventContainer;

    public LogFileLoader() {
        logEventContainer = new LogEventContainer();
    }

    public void load(final String logFilePath, final String logFilePattern) throws IOException, ParseException {
        InputStreamReader inputReader = new InputStreamReader(new FileInputStream(logFilePath));
        BufferedReader reader = new BufferedReader(inputReader);

        String fileString = null;
        StringBuilder content = new StringBuilder();
        StringBuilder line = new StringBuilder();

        PatternParser patternParser = new PatternParser(logFilePattern);
        Pattern recordPattern = patternParser.getRecordPattern();
        LogRecordCreator logRecordCreator = new LogRecordCreator(recordPattern, patternParser.getLogFields());

        try {
            while ((fileString = reader.readLine()) != null) {
                line.append(fileString).append('\n');

                if ((recordPattern.matcher(line).find()) && (content.length() > 0)) {
                    addLogRecord(logRecordCreator.createLogRecord(content.toString()));
                    content.setLength(0);
                }
                content.append(line);
                line.setLength(0);
            }

            if (content.length() > 0) {
                addLogRecord(logRecordCreator.createLogRecord(content.toString()));
            }
        } finally {
            reader.close();
            inputReader.close();
        }
    }

    private void addLogRecord(final LogRecord logRecord) throws ParseException {
        if (logRecord != null) {
            LogEvent logEvent = new FileLogEvent(logRecord);
            logEventContainer.notifyListeners(logEvent);
        }
    }

    public void addListener(final LogEventListener listener) {
        if (listener != null) {
            logEventContainer.addListener(listener);
        }
    }

    public void removeListener(final LogEventListener listener) {
        logEventContainer.removeListener(listener);
    }
}
